package dispatch

import (
	"context"
	"encoding/json"
	"sync"

	"gitee.com/saroeleven/ginrcpv2/etcdmgr/etcdclient"
	"gitee.com/saroeleven/ginrcpv2/etcdmgr/registry"
	"gitee.com/saroeleven/ginrcpv2/log"
)

// dispatch 维护服务的哈希map
type dispatch struct {
	hzNodeServices sync.Map
	loadOnce       sync.Once
}

var d = &dispatch{}

func dispatchInstance() *dispatch {
	d.loadOnce.Do(func() {
		initServiceXNode()
	})
	return d
}

func initServiceXNode() {
	client, err := etcdclient.NewEtcdClient()
	if err != nil {
		log.Errorf("failed to create etcd client: %v", err)
		return
	}

	if err := client.LoadAndWatchV3(
		context.TODO(),
		registry.XnodePrefix,
		nodeUpdate,
		nodeDelete,
		client.WithPrefix(), // 通过前缀,监听所有服务节点
	); err != nil {
		log.Errorf("failed to watch config: %v", err)
	}
}

func nodeUpdate(key, value []byte) {
	var svr registry.Service
	if err := json.Unmarshal(value, &svr); err != nil {
		log.Errorf("failed to unmarshal service entry: %v", err)
		return
	}
	d.hzNodeServices.Store(string(key), svr)
	log.Infof("stored service entry: [key:%s] [value:%+v]", string(key), svr)
}

func nodeDelete(key, value []byte) {
	d.hzNodeServices.Delete(string(key))
	log.Infof("removed service entry: [key:%s]", string(key))
}

// NodePord returns a list of services with the given name
func (d *dispatch) NodePord(svrName string) (list []registry.Service) {
	d.hzNodeServices.Range(func(key, value any) bool {
		service, _ := value.(registry.Service)
		if service.Name == svrName {
			list = append(list, service)
		}
		return true
	})
	return list
}
